package com.zonski.jbots.game.entity;

import com.zonski.jbots.engine.*;
import com.zonski.jbots.engine.entity.MovingEntity;
import com.zonski.jbots.engine.entity.Mind;
import com.zonski.jbots.game.JBotsConstants;
import com.zonski.jbots.game.EntityHelper;
import com.zonski.jbots.game.resources.BombMaker;
import com.zonski.jbots.game.resources.EggMaker;

/**
 * Mind for bad robots
 */
public class BadBotMind extends SeekerBotMind
{
    private static final int BLOW_CHARGER_CHANCE = 10;

    /**
     * the number of updates that we run away from a bomb we planted
     */
    private static final int BOMB_RUN_DEFAULT = 200;

    private int bombRun;
    private int laying;
    private boolean occupied;

    private boolean bombs;
    private boolean eggs;
    private boolean lastBombs;
    private boolean lastEggs;

    private int direction;
    private boolean shielded;
    private int totalVisibleCharge;
    private String preferredBot;

    public BadBotMind(String preferredBot)
    {
        this.deathUpdates = 2;
        this.preferredBot = preferredBot;
    }

    public void update(Engine engine)
        throws Exception
    {
        this.lastBombs = this.bombs;
        this.lastEggs = this.eggs;
        this.bombs = false;
        this.eggs = false;
        this.totalVisibleCharge = 0;

        if(this.getEntity().getMode() == Modes.DEAD)
        {
            this.getEntity().setRemovable(true);
            // play the dead robot sound
            this.getEntity().getDevice().play("DeadBot", 1);
            // put down some goodies
            Entity capacity = EntityHelper.addEntity(JBotsConstants.CAPACITY, this.getEntity(), engine, 0);
            EntityHelper.centreAtClosestTile(
                    capacity.bounds, this.getEntity().bounds, engine.getRoom()
            );
            capacity.setMaxCharge(this.getEntity().getMaxCharge()/2);
            return;
        }
        this.bombRun--;
        MovingEntity entity = (MovingEntity)this.getEntity();
        this.occupied = EntityHelper.isOccupied(entity, engine);
        QuickVector resources = entity.getResources();
        this.laying --;
        if(!entity.isMovable())
        {
            for(int i=resources.size(); i>0; )
            {
                i--;
                Object o = resources.elementAt(i);
                if(o instanceof EggMaker)
                {
                    if(this.laying == 0)
                    {
                        ((EggMaker)o).stopUsing();
                    }
                }else if(o instanceof UsableResource){
                    ((UsableResource)o).stopUsing();
                }
            }
        }

        super.update(engine);
    }

    protected void directionDecided(int direction, int desirability, int minDesirability)
    {
        //System.out.println("min : "+minDesirability);
        if(minDesirability >= -10)
        {
            if(this.laying < 0 && !this.occupied && !this.lastBombs)
            {
                // feels safe to lay an egg
                //EggMaker eggMaker = (EggMaker)entity.getResource(toCreate);
                Entity entity = this.getEntity();
                //int charge = EntityHelper.getCharge(entity);
                int div = Math.max(1, entity.layerId - 1);
                int charge = entity.getCharge();
                int maxCharge = entity.getMaxCharge();
                if(charge > Math.min(maxCharge, 100)/(5-div))
                {
                    //div = 0x01 << (div-1);
                    EggMaker eggMaker = null;
                    QuickVector vector = entity.getResources();
                    for(int i=vector.size(); i>0; )
                    {
                        i--;
                        Object o = vector.elementAt(i);
                        if(o instanceof EggMaker)
                        {
                            EggMaker e = (EggMaker)o;
                            //System.out.println(e.getToCreate());
                            if(e.getMinCharge() < charge && e.getMinCharge() < ((this.totalVisibleCharge+charge)/div+minDesirability) &&
                               (eggMaker == null ||
                                    (eggMaker.getMinCharge() < e.getMinCharge() ||
                                    this.preferredBot.equals(eggMaker.getToCreate()) /*||
                                    Math.abs(random.nextInt())%6 < div))*/)))
                            {
                                eggMaker = e;
                            }
                        }
                    }

                    if(eggMaker != null)
                    {
                        //System.out.println(entity.layerId + " decided to use eggmaker : "+eggMaker.getToCreate());
                        int minCharge = eggMaker.getMinCharge();
                        this.laying = (minCharge / eggMaker.getChargeIncrement())*eggMaker.getChargeDiv() + eggMaker.getChargeDiv();
                        eggMaker.startUsing(entity.direction);
                    }
                }
            }
        }else if(minDesirability < -100 && this.laying >= 0){
            // get out of there
            MovingEntity entity = (MovingEntity)this.getEntity();
            this.laying = 0;
            QuickVector vector = this.getEntity().getResources();
            for(int i=vector.size(); i>0; )
            {
                i--;
                Resource resource = (Resource)vector.elementAt(i);
                if(resource.isBeingUsed())
                {
                    if(resource instanceof EggMaker)
                    {
                        ((UsableResource)resource).stopUsing();
                    }
                }
            }
        }
    }

    protected int getDesirability(QuickVector entities, int distance, int direction)
    {
        if(direction != this.direction)
        {
            this.shielded = false;
            this.direction = direction;
        }
        Entity entity = this.getEntity();
        int desirability;
        if(distance == 1)
        {
            if(direction == entity.direction)
            {
                desirability = 10;
            }else{
                desirability = this.random.nextInt()%12;
            }
        }else{
            desirability = 0;
        }
        if(entities != null)
        {
            for(int i=entities.size(); i>0; )
            {
                i--;
                Entity found = (Entity)entities.elementAt(i);
                desirability += getDesirability(found, direction, distance);
            }
        }

        if(direction != entity.direction && distance != 0)
        {
            desirability = (desirability / distance);
            if((desirability % distance) >  0)
            {
                desirability ++;
            }
        }else if(distance == 0){
            // get out of here!
            if(this.lastBombs)
            {
                desirability = -2000;
            }
        }


        return desirability;
    }

    private int getDesirability(Entity found, int direction, int distance)
    {
        int desirability;
        Entity entity = this.getEntity();
        if(found.entityType.getId() == JBotsConstants.BOMB_ID && distance < 3)
        {
            // get out of here!
            //BombMind mind = (BombMind)((MovingEntity)found).getMind();
            // TODO : factor in the amount to count to
            desirability = -(found.getEffectiveModeUpdates()) - 100;
            this.bombs = true;
        }else if(found.entityType.getId() == JBotsConstants.EXPLOSION_ID && distance < 3){
            desirability = -30;
        }else if(JBotsConstants.isObstacle(found.entityType.getId())){
            desirability = -5/(distance+1);
            this.shielded = true;
        }else if(found.entityType.getId() == JBotsConstants.RECHARGE_ID ||
                found.entityType.getId() == JBotsConstants.CHARGE_ID){
            if(found.getCharge() > 0)
            {
                this.totalVisibleCharge += found.getCharge();
                desirability = ((this.getEntity().getMaxCharge() - this.getEntity().getCharge())*2)/3;
                if(desirability == 0 && distance <= 1 && !this.occupied && !this.lastEggs &&
                        found.entityType.getId() == JBotsConstants.RECHARGE_ID)
                {
                    // maybe we'll blow it up
                    if(this.random.nextInt() % BLOW_CHARGER_CHANCE == 0)
                    {
                        UsableResource bombMaker = (UsableResource)entity.getResource(JBotsConstants.BOMB);
                        if(bombMaker != null)
                        {
                            bombMaker.startUsing(direction);
                            this.bombRun = BOMB_RUN_DEFAULT;
                        }
                    }
                }
            }else{
                desirability = 0;
            }
        }else if(found.entityType.getId() == JBotsConstants.CAPACITY_ID){
            desirability = found.getMaxCharge() / (distance+1) + found.getCharge();
        }else if(found.layerId != entity.layerId){
            if(JBotsConstants.isBot(found.entityType.getId()))
            {
                if(this.shielded)
                {
                    desirability = -10/(distance+1);
                }else{
                    desirability = -200;
                    if(!this.occupied &&
                            // always shoot at the competition
                           (found.entityType.getId() == JBotsConstants.BOT_ID ||
                            this.random.nextInt() % ((this.getEntity().getMaxCharge() - this.getEntity().getCharge())/40 + 1) == 0))
                    {
                        // launch a comet at it while we're here
                        UsableResource cometMaker = (UsableResource)entity.getResource(JBotsConstants.COMET);
                        if(cometMaker != null)
                        {
                            cometMaker.startUsing(direction);
                        }
                    }

                }
            }else{
                desirability = -200/(distance+1);
            }
        }else{
            if(found.entityType.getId() == JBotsConstants.EGG_ID && distance < 3)
            {
                // it's my baby!
                this.eggs = true;
            }
            desirability = 0;
        }
        if(this.bombRun > 0)
        {
            desirability += distance;
        }
        return desirability;
    }

    protected boolean isBlocker(Entity entity)
    {
        boolean blocker;
        if(this.bombRun > 0 || this.lastBombs || this.lastEggs)
        {
            blocker = super.isBlocker(entity);
        }else{
            blocker = entity.entityType.getId() == JBotsConstants.ROCK_ID;
        }
        return blocker;
    }

    public void collision(Engine engine, CollisionData data)
    {
        super.collision(engine, data);
        // if it's a wall, blow it up
        if(!this.occupied && !this.eggs && !this.lastEggs &&
                (data.with.entityType.getId() == JBotsConstants.TEMP_ROCK_ID) ||
                (data.with.entityType.getId() == JBotsConstants.TREE_ROCK_ID))
        {
            Entity entity = this.getEntity();
            BombMaker bombMaker = (BombMaker)entity.getResource(JBotsConstants.BOMB);
            if(bombMaker != null)
            {
                bombMaker.startUsing(entity.direction);
                this.bombRun = BOMB_RUN_DEFAULT;
            }
        }
    }

    public Mind copy()
    {
        return new BadBotMind(this.preferredBot);
    }
}
